---
title: "Cleavage theory meets civil society: A framework and research agenda"
date: "`r Sys.Date()`"
output: 
  html_document:
    toc: true
    toc_depth: 3
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
rm(list = ls())

library(haven)
library(dplyr)
library(psych)
library(Amelia)
library(ggplot2)
library(ggrepel)
library(countrycode)
library(stringr)
library(tidyr)
library(kableExtra)
library(readxl)
library(forcats)
library(here)

```

# V-Party dataset

## Items

1. v2pasoctie: To what extent does this party maintain ties to prominent social organizations?
2. v2pafunds: What were the major sources of party funds for this election campaign?
    - Formal state subsidies for political parties. (0=No, 1=Yes) [v2pafunds_0]
    - Large-scale donations from individuals. (0=No, 1=Yes) [v2pafunds_1]
    - Large-scale donations from companies. (0=No, 1=Yes) [v2pafunds_2]
    - **Large-scale donations from civil society organizations (including trade unions). (0=No, 1=Yes) [v2pafunds_3]**
    - Membership fees and small-scale supporters' donations. (0=No, 1=Yes) [v2pafunds_4]
    - Informal use of state resources as incumbent party. (0=No, 1=Yes) [v2pafunds_5]
    - Funds of the party leader. (0=No, 1=Yes) [v2pafunds_6]
    - Funds of candidates. (0=No, 1=Yes) [v2pafunds_7]


### Centered indicators by country

```{r, echo=FALSE}

dat <- read_dta(here("V-Dem-CPD-Party-V2.dta")) %>% 
  filter(country_name %in% c("Austria", "France", "Germany", "Netherlands", "Switzerland")) %>% 
  select(country_name, year,  v2pavote, v2paenname, v2pashname, v2paid,
        v2pasoctie, v2pafunds_3, CHES_ID) %>% 
  group_by(country_name, v2paenname) %>%
  filter(!all(is.na(v2pasoctie) & is.na(v2pafunds_3))) %>%
  ungroup() %>% 
  filter((year==2017 & country_name %in% c("France", "Germany", "Netherlands")) | 
          (year==2019 & country_name %in% c("Austria", "Switzerland")))
  

dat <- dat %>% 
  select(-year) %>% 
  mutate(label_name=paste0(v2paenname, " (", country_name, ")")) %>% 
  mutate(iso2code=countrycode(country_name, "country.name", "iso2c")) %>% 
  mutate(label_name_short=paste0(v2pashname, " (", iso2code, ")")) %>% 
  group_by(country_name) %>% 
  mutate(v2pasoctie_cen=v2pasoctie-mean(v2pasoctie, na.rm=TRUE)) %>%
  mutate(v2pafunds_3_cen=v2pafunds_3-mean(v2pafunds_3, na.rm=TRUE)) %>%
  ungroup()

ches <- read_dta(here("CHES dataset means v3.dta")) %>% 
  select(party_id, family) %>% 
  distinct() %>% 
  filter(!(party_id==310 & family==9))

dat <- left_join(dat, ches, by=c("CHES_ID"="party_id")) %>% 
  mutate(family=case_when(family==1 ~ "FarRight",
family==2 ~ "Conserv",
family==3 ~ "Liberal",
family==4 ~ "ChrisDem",
family==5 ~ "SocDem",
family==6 ~ "RadLeft",
family==7 ~ "Green",
family==8 ~ "Region",
family==9 ~ as.character(NA),
family==10 ~ "Confess",
family==11 ~ "Agrar",
v2paenname=="Social Democratic Party of Switzerland" ~ "SocDem",
v2paenname=="Swiss People's Party" ~ "FarRight",
v2paenname=="Radical Democratic Party" ~ "Liberal",
v2paenname=="Green Liberal Party" ~ "Green",
v2paenname=="Green Party" ~ "Green",
v2paenname=="Catholic Conservative / Christian Democratic Peoples Party" ~ "ChrisDem",
v2paenname=="NEOS – The New Austria" ~ "Liberal"
)) %>% 
mutate(family=ifelse(str_detect(v2paenname, "Alternative for Germany"), "FarRight", family)) %>% 
mutate(family = replace(family, v2paenname == "Freedom Party of Austria" & label_name_short == "FPO (AT)", "rad right")) %>%
  mutate(family = replace(family, v2paenname == "The Greens -- The Green Alternative" & label_name_short == "GRUENE (AT)", "green")) %>%
  mutate(family = replace(family, v2paenname == "NEOS – The New Austria" & label_name_short == "NEOS (AT)", "liberal")) %>%
  mutate(family = replace(family, v2paenname == "Austrian People's Party" & label_name_short == "OVP (AT)", "christdem")) %>%
  mutate(family = replace(family, v2paenname == "Social Democratic Party of Austria" & label_name_short == "SPO (AT)", "socialist")) %>%
  mutate(family = replace(family, v2paenname == "Unbowed France" & label_name_short == "FI (FR)", "rad left")) %>%
  mutate(family = replace(family, v2paenname == "National Front" & label_name_short == "FN (FR)", "rad right")) %>%
  mutate(family = replace(family, v2paenname == "The Republic Onwards!" & label_name_short == "LaREM (FR)", "liberal")) %>%
  mutate(family = replace(family, v2paenname == "Socialist Party" & label_name_short == "PS (FR)", "socialist")) %>%
  mutate(family = replace(family, v2paenname == "Alternative for Germany" & label_name_short == "AfD (DE)", "rad right")) %>%
  mutate(family = replace(family, v2paenname == "Alliance 90 / Greens" & label_name_short == "B90/Grue (DE)", "green")) %>%
  mutate(family = replace(family, v2paenname == "Free Democratic Party" & label_name_short == "FDP (DE)", "liberal")) %>%
  mutate(family = replace(family, v2paenname == "The Left" & label_name_short == "Linke (DE)", "rad left")) %>%
  mutate(family = replace(family, v2paenname == "Social Democratic Party of Germany" & label_name_short == "SPD (DE)", "socialist")) %>%
  mutate(family = replace(family, v2paenname == "Christian Democratic Appeal" & label_name_short == "CDA (NL)", "christdem")) %>%
  mutate(family = replace(family, v2paenname == "Democrats 66" & label_name_short == "D66 (NL)", "liberal")) %>%
  mutate(family = replace(family, v2paenname == "GreenLeft" & label_name_short == "GL (NL)", "green")) %>%
  mutate(family = replace(family, v2paenname == "Party for Freedom" & label_name_short == "PVV (NL)", "rad right")) %>%
  mutate(family = replace(family, v2paenname == "Labour" & label_name_short == "PvdA (NL)", "socialist")) %>%
  mutate(family = replace(family, v2paenname == "Socialist Party" & label_name_short == "SP (NL)", "rad left")) %>%
  mutate(family = replace(family, v2paenname == "People's Party for Freedom and Democracy" & label_name_short == "VVD (NL)", "liberal")) %>%
  mutate(family = replace(family, v2paenname == "Radical Democratic Party" & label_name_short == "FDP (CH)", "liberal")) %>%
  mutate(family = replace(family, v2paenname == "Green Liberal Party" & label_name_short == "GPL (CH)", "green")) %>%
  mutate(family = replace(family, v2paenname == "Green Party" & label_name_short == "Grue (CH)", "green")) %>%
  mutate(family = replace(family, v2paenname == "Catholic Conservative / Christian Democratic Peoples Party" & label_name_short == "KK/CVP (CH)", "christdem")) %>%
  mutate(family = replace(family, v2paenname == "Social Democratic Party of Switzerland" & label_name_short == "SP (CH)", "socialist")) %>%
  mutate(family = replace(family, v2paenname == "Swiss People's Party" & label_name_short == "SVP (CH)", "rad right")) %>% 
  mutate(family=case_when(family=="christdem" ~ "ChrisDem",
                          family=="liberal" ~ "Liberal",
                          family=="socialist" ~ "SocDem",
                          family=="rad left" ~ "RadLeft",
                          family=="rad right" ~ "FarRight",
                          family=="green" ~ "Green",
                          TRUE ~ family))

ches_families <- dat %>% 
  select(country_name, v2paenname, label_name_short) %>% 
  unique() %>% 
  write.csv("ches_families.csv", row.names=FALSE)

```

- The names ending with _cen are centered by country.
- The different factors are correlated, although I did not rotate them.

## Figure 1, main text

### Donations and organizational ties (centered)

```{r, echo=FALSE, width=6, height=8}

dat_families <- dat %>% 
  select(v2paenname, label_name_short, family)

# Define the color scheme
party_colors <- c(
  SocDem = "red",
  FarRight = "blue",
  Liberal = "yellow",
  Green = "green",
  ChrisDem = "orange",
  Conserv = "black",
  RadLeft = "purple"
)

library(ggforce)

ggplot(dat, aes(x = v2pafunds_3_cen, y = v2pasoctie_cen, 
                size = v2pavote)) +
  geom_point(aes(fill=family), shape = 21, color="black") +
  geom_text_repel(aes(label = label_name_short), min.segment.length = 4, max.overlaps = 999) +
  labs(x = "Donations from civil society (country-mean centered)", y = "Organizational ties (country-mean centered)") +
  scale_size_continuous("Average vote share:", range = c(2, 4.5), guide = guide_legend(nrow = 1)) + 
  scale_fill_manual("Party family:", values = party_colors, guide = guide_legend(ncol = 4)) +
  theme_minimal() +
  guides(size = guide_legend(order = 1),
         fill = guide_legend(order = 2)) +
  theme(legend.position = "bottom", 
        legend.direction = "horizontal",
        legend.box = "vertical") +
  geom_ellipse(aes(x0 = 0, y0 = 1.05, a = 0.09, b = 0.17, angle = 0), size=0.3, color = "black", linetype="dashed", fill = NA) + #SVP circle
  geom_ellipse(aes(x0 = -0.11, y0 = -2.02, a = 0.08, b = 0.15, angle = 0), size=0.3, color = "black", linetype="dashed", fill = NA) + # AfD circle
  geom_ellipse(aes(x0 = 0.085, y0 = 0.15, a = 0.05, b = 0.2, angle = 0), size=0.3, color = "black", linetype="dashed", fill = NA) # Grunen circle

# ggsave(
#     filename = "party_scatter.png",
#     dpi=600,
#     width = 6, height = 7,
#     units = "in"
# )

```



# EVS and WVS joint file

## Timeframe

- I look at the joint file of the EVS 2017 and the WVS 2022. 

## Items

- Membership:
  - A065	Member: Belong to religious organization
  - A066	Member: Belong to education, arts, music or cultural activities
  - A067	Member: Belong to labour unions
  - A068	Member: Belong to political parties [I don't use it for now.]
  - A071	Member: Belong to conservation, the environment, ecology, animal rights
  - A072	Member: Belong to professional associations
  - A074	Member: Belong to sports or recreation
  - A078	Member: Belong to consumer groups
  - A079	Member: Belong to other groups
  - A080_01	Member: Humanitarian or charitable organization
  - A080_02	Member:  Self-help group, mutual aid group
- The party preference question has been asked differently between the two surveys. For the purposes of the  analysis I use them as equivalent. The different versions have been:
  - WVS:Which party would you vote for: first choice (WVS5, E179_WVS7)
  - EVS: Which political party appeals to you most (EVS5, E181_EVS5)

## Method

- I look at the level of membership in the electorate of different parties.

  
```{r, echo=FALSE, message=FALSE, warning=FALSE, include=FALSE}

evs_wvs <- read_dta(here("ZA7505_v5-0-0.dta"))


dat <- evs_wvs %>% 
  mutate(weight=case_when(is.na(gwght) & !is.na(wght_eq1000) ~ wght_eq1000,
                          !is.na(gwght) ~ gwght,
                          TRUE ~ 1)) %>% 
  select(cntry, year, E181_EVS5, E179_WVS7, A065, A066, A067, A071, A072, A074, A078, A079, A080_01, A080_02, weight) %>% # A067 would be political parties
  mutate_at(vars(cntry, E181_EVS5, E179_WVS7), ~as.character(as_factor(.))) %>% 
  filter(cntry %in% c("Austria", "France", "Germany", "Netherlands", "Switzerland")) %>% 
  group_by(E181_EVS5) %>% 
  mutate(frequency=n()) %>%
  ungroup() %>% 
  mutate(EVS_party = case_when(
    frequency < 20 ~ "Other",
    grepl("Other", E181_EVS5, ignore.case = TRUE) ~ "Other",
    grepl("No [no other] party appeals to me", E181_EVS5, ignore.case = TRUE) ~ "No party",
    grepl("No answer", E181_EVS5, ignore.case = TRUE) ~ "No party",
    grepl("Not asked in survey", E181_EVS5, ignore.case = TRUE) ~ "No party",
    grepl("Don´t know", E181_EVS5, ignore.case = TRUE) ~ "No party",
    grepl("Left Wing Extremist Parties", E181_EVS5) ~ "Other",
    TRUE ~ gsub("^(\\w+:\\s)", "", E181_EVS5)  # Removing country code and space
  )) %>% 
  mutate(EVS_party=ifelse(EVS_party=="No party", as.character(NA), EVS_party)) %>% 
  group_by(E179_WVS7) %>% 
  mutate(frequency=n()) %>%
  ungroup() %>% 
  mutate(WVS_party = case_when(
    frequency < 20 ~ "Other",
    grepl("Other", E179_WVS7, ignore.case = TRUE) ~ "Other",
    grepl("No [no other] party appeals to me", E179_WVS7, ignore.case = TRUE) ~ "No party",
    grepl("No answer", E179_WVS7, ignore.case = TRUE) ~ "No party",
    grepl("Not asked in survey", E179_WVS7, ignore.case = TRUE) ~ "No party",
    grepl("Don´t know", E179_WVS7, ignore.case = TRUE) ~ "No party",
    grepl("Left Wing Extremist Parties", E179_WVS7) ~ "Other",
    TRUE ~ gsub("^(\\w+:\\s)", "", E179_WVS7)  # Removing country code and space
  )) %>% 
  mutate(WVS_party=ifelse(WVS_party=="No party", as.character(NA), WVS_party)) %>% 
  select(-frequency, -E179_WVS7, -E181_EVS5) %>% 
  mutate(iso2code=countrycode(cntry, "country.name", "iso2c")) %>%
  mutate(EVS_party=paste0(iso2code, ": ", EVS_party)) %>% 
  mutate(WVS_party=paste0(iso2code, ": ", WVS_party))

# Define the mappings for party names
party_mapping <- list(
  "AT: List Kurz / Austrian People's Party - ÖVP" = "Austrian People's Party (ÖVP)",
  "AT: Social Democratic Party of Austria - SPÖ" = "Social Democratic Party (SPÖ)",
  "AT: Freedom Party of Austria - FPÖ" = "Freedom Party (FPÖ)",
  "AT: The Greens - The Green Alternative" = "The Greens",
  "AT: The new Austria - NEOS" = "NEOS",
  "AT: List Peter Pilz" = "Other",
  "AT: Other" = "Other",
  "AT: NA" = NA,
  "FR: France Arise" = "France Arise",
  "FR: Unsubmissive France" = "Unsubmissive France",
  "FR: National Front" = "National Front",
  "FR: The Republic Onwards" = "The Republic Onwards",
  "FR: Socialist Party" = "Socialist Party",
  "FR: The Republicans" = "The Republicans",
  "FR: Democratic Movement" = "Democratic Movement",
  "FR: Europe Ecology – The Greens" = "The Greens",
  "FR: Communist Party" = "Communist Party",
  "FR: Union of Democrats and Independents" = "Union of Democrats and Independents",
  "FR: Other" = "Other",
  "FR: NA" = NA,
  "DE: The Green Party" = "Alliance 90/The Greens",
  "DE: The Left" = "The Left",
  "DE: Christian Democratic Party/Christian Social Union" = "Christian Democratic Union of Germany; Christian Social Union in Bavaria",
  "DE:  Christian Democratic Union of Germany; Christian Social Union in Bavaria" = "Christian Democratic Union of Germany; Christian Social Union in Bavaria",
  "DE: German Social-Democratic Party" = "Social Democratic Party",
  "DE: Alternative for Germany" = "Alternative for Germany",
  "DE: German Liberal Party" = "Free Democratic Party",
  "DE: Other" = "Other",
  "DE: NA" = NA,
  "NL: Christian Union" = "Christian Union Party",
  "NL: Christian Democratic Appeal" ~ "Christian Democratic Appeal",
  "NL: GreenLeft" = "Green Left",
  "NL: Labour Party" = "Labour Party",
  "NL: People's Party for Freedom and Democracy" = "People's Party for Freedom and Democracy",
  "NL: People´s Party for Freedom and Democracy" = "People's Party for Freedom and Democracy",
  "NL: Democrats 66" = "Democrats 66",
  "NL: Socialist Party" = "Socialist Party",
  "NL: Party for Freedom" = "Party for Freedom",
  "NL: Party for the Animals" = "Party for the Animals",
  "NL: Forum for Democracy" = "Forum for Democracy",
  "NL: Reformed Political Party" = "Reformed Political Party",
  "NL: 50Plus" = "50Plus",
  "NL: Other" = "Other",
  "NL: NA" = NA,
  "CH: Social Democratic Party  (socialist)" = "Social Democratic Party",
  "CH: Christian Democratic Party" = "Christian Democratic Party",
  "CH: The Liberals (Merge from Radicals and Liberals)" = "The Liberals",
  "CH: Swiss People's Party" = "Swiss People's Party",
  "CH: Green Liberal Party" = "Green Liberal Party",
  "CH: Evangelical People's Party" = "Evangelical People's Party",
  "CH: Green Party" = "Green Party",
  "CH: Conservative Democratic Party" = "Conservative Democratic Party",
  "CH: Swiss Labour Party" = "Swiss Labour Party",
  "CH: The alternative Left" = "The alternative Left",
  "CH: Federal Democratic Union" = "Federal Democratic Union",
  "CH: Other" = "Other",
  "CH: NA" = NA
)

# Verify that all unique values of EVS_party are included in the party_mapping
unique_evs_party <- unique(dat$EVS_party)
missing_mappings <- unique_evs_party[!unique_evs_party %in% names(party_mapping)]

if (length(missing_mappings) > 0) {
  warning("The following EVS_party values are missing from the party_mapping and will be mapped to 'Other': ", paste(missing_mappings, collapse = ", "))
  for (party in missing_mappings) {
    party_mapping[[party]] <- "Other"
  }
}

# Function to harmonize party names
harmonize_party <- function(evs_party, wvs_party) {
  if (!is.na(wvs_party)) {
    return(wvs_party)
  } else if (!is.na(evs_party)) {
    return(party_mapping[[evs_party]])
  } else {
    return(NA)
  }
}

# Apply the function to create the new party column
dat <- dat %>%
  mutate(new_party = mapply(harmonize_party, EVS_party, WVS_party)) %>%
  mutate_at(vars(WVS_party, EVS_party), ~ ifelse(. %in% c("AT: NA", 
                                             "FR: NA", 
                                             "DE: NA", 
                                             "NL: NA", 
                                             "CH: NA",
                                             "NL: No right to vote", 
                                             "NL: Not applicable"), as.character(NA), 
                                             sub("^\\w{2}: ", "", .))) %>% 
  mutate_at(vars(WVS_party, EVS_party), ~ case_when(. == "Independent candidate" ~ "Other",
                               TRUE ~ .)) %>% 
  mutate(new_party=ifelse(!is.na(WVS_party), WVS_party, EVS_party)) %>% 
  mutate(new_party=paste0(iso2code, ": ", new_party)) %>% 
  mutate(new_party=case_when(
    new_party=="NL: People´s Party for Freedom and Democracy" ~ "NL: People's Party for Freedom and Democracy",
    new_party=="NL: GreenLeft" ~ "NL: Green Left",
    new_party=="NL: Christian Union Party" ~ "NL: Christian Union",
    new_party=="DE: German Social-Democratic Party" ~ "DE: Social Democratic Party",
    new_party=="DE:  Christian Democratic Union of Germany; Christian Social Union in Bavaria" ~ "DE: Christian Democratic Party/Christian Social Union",
    TRUE ~ new_party
  )) %>% 
  mutate_at(vars(new_party), ~ ifelse(. %in% c("AT: NA", 
                                             "FR: NA", 
                                             "DE: NA", 
                                             "NL: NA", 
                                             "CH: NA",
                                             "NL: No right to vote", 
                                             "NL: Not applicable"), as.character(NA), 
                                             .)) %>% 
  mutate(new_party=ifelse(grepl("native for Germany", new_party), "DE: Alternative for Germany", str_squish(new_party)))
  
# Define the abbreviations for party names
party_abbreviations <- list(
  "AT: List Kurz / Austrian People's Party - ÖVP" = "ÖVP",
  "AT: Social Democratic Party of Austria - SPÖ" = "SPÖ",
  "AT: Freedom Party of Austria - FPÖ" = "FPÖ",
  "AT: Other" = "Other",
  "AT: The Greens - The Green Alternative" = "Greens",
  "AT: The new Austria - NEOS" = "NEOS",
  "AT: List Peter Pilz" = "PILZ",
  "FR: France Arise" = "DLF",
  "FR: Unsubmissive France" = "LFI",
  "FR: Other" = "Other",
  "FR: National Front" = "FN",
  "FR: The Republic Onwards" = "LREM",
  "FR: Socialist Party" = "PS",
  "FR: The Republicans" = "LR",
  "FR: Democratic Movement" = "MoDem",
  "FR: Europe Ecology – The Greens" = "EELV",
  "FR: Communist Party" = "PCF",
  "FR: Union of Democrats and Independents" = "UDI",
  "DE: The Green Party" = "Die Grünen",
  "DE: The Left" = "LINKE",
  "DE: Christian Democratic Party/Christian Social Union" = "CDU/CSU",
  "DE: Social Democratic Party" = "SPD",
  "DE: Alternative for Germany" = "AfD",
  "DE: Other" = "Other",
  "DE: German Liberal Party" = "FDP",
  "NL: Christian Union" = "CU",
  "NL: Christian Democratic Appeal" ~ "CDA",
  "NL: Other" = "Other",
  "NL: Socialist Party" = "SP",
  "NL: Green Left" = "GL",
  "NL: Labour Party" = "PvdA",
  "NL: People's Party for Freedom and Democracy" = "VVD",
  "NL: Democrats 66" = "D66",
  "NL: Christian Democratic Appeal" = "CDA",
  "NL: 50Plus" = "50Plus",
  "NL: Party for Freedom" = "PVV",
  "NL: Party for the Animals" = "PvdD",
  "NL: Forum for Democracy" = "FvD",
  "NL: Reformed Political Party" = "SGP",
  "CH: Social Democratic Party (socialist)" = "SP",
  "CH: Christian Democratic Party" = "CVP",
  "CH: The Liberals (Merge from Radicals and Liberals)" = "FDP",
  "CH: Swiss People's Party" = "SVP",
  "CH: Green Liberal Party" = "GLP",
  "CH: Evangelical People's Party" = "EVP",
  "CH: Green Party" = "GPS",
  "CH: Conservative Democratic Party" = "BDP",
  "CH: Swiss Labour Party" = "PST",
  "CH: Other" = "Other",
  "CH: The alternative Left" = "AL",
  "CH: Federal Democratic Union" = "EDU",
  "DE: Alliance 90/The Greens" = "Die Grünen",
  "DE: Free Democratic Party" = "FDP",
  "NL: Juiste Antwoord 2021" = "JA21",
  "NL: Volt Europe" = "Volt",
  "NL: Farmer–Citizen Movement" = "BBB"
)

# Function to map full party names to abbreviations
map_to_abbreviation <- function(party_name) {
  if (!is.na(party_name) && !is.null(party_abbreviations[[party_name]])) {
    return(party_abbreviations[[party_name]])
  } else {
    return(NA)
  }
}

# Apply the function to create the new party_abbreviation column
dat <- dat %>%
  rowwise() %>%
  mutate(party_abbreviation = map_to_abbreviation(new_party)) %>% 
  group_by(party_abbreviation) %>%
  mutate(not_unique = ifelse(n_distinct(iso2code) > 1, 1, 0)) %>%
  ungroup(.) %>% 
  mutate(party_abbreviation = case_when(not_unique == 1 & !is.na(party_abbreviation) ~ paste0(party_abbreviation, " (", iso2code, ")"), 
                                        not_unique == 0 & !is.na(party_abbreviation) ~ party_abbreviation,
                                        TRUE ~ as.character(NA))) %>% 
  mutate_at(vars(starts_with("A0")), ~ ifelse(.<0, 0, .)) %>% 
  mutate(involvement = rowSums(across(c("A065", "A066", "A067", "A071", "A072", 
                                         "A074", "A078", "A079", "A080_01", 
                                         "A080_02")), na.rm = TRUE)) %>% 
  mutate(involvement_2 = ifelse(involvement>0, 1, 0)) %>% 
  rename(
    rel_org   = A065,    # Religious organization membership
    arts      = A066,    # Education, arts, music or cultural activities
    labour    = A067,    # Labour unions
    # political = A068,  # Political parties (not used for now)
    enviro    = A071,    # Conservation, environment, ecology, animal rights
    prof      = A072,    # Professional associations
    sports    = A074,    # Sports or recreation groups
    consumer  = A078,    # Consumer groups
    other     = A079,    # Other groups
    humanit   = A080_01, # Humanitarian or charitable organization
    self_help = A080_02  # Self-help / mutual aid group
  ) %>% 
  mutate_at(vars(rel_org, arts, labour, enviro, 
         prof, sports, consumer, other, humanit, self_help), ~ifelse(is.na(.), 0, .)) %>% 
  mutate(party_abbreviation=ifelse(is.na(party_abbreviation), "No party", party_abbreviation))



```


```{r, echo=FALSE, width=6, height=6, warning=FALSE, message=FALSE}

library(dplyr)
library(tidyr)

# Define the dummy columns for organizations
dummy_vars <- c("rel_org", "arts", "labour", "enviro", "prof", 
                "sports", "consumer", "other", "humanit", "self_help")

# Reshape the dataset to long format: one row per respondent per organization type
dat_long <- dat %>%
  select(cntry, party_abbreviation, weight, all_of(dummy_vars)) %>%
  pivot_longer(
    cols = all_of(dummy_vars),
    names_to = "org_type",
    values_to = "membership"
  )

# Compute denominators for each organization type within each country:
# total_members = total weight for respondents with membership == 1
# total_nonmembers = total weight for respondents with membership == 0
denom_long <- dat_long %>%
  group_by(cntry, org_type) %>%
  summarise(
    total_members   = sum(weight * (membership == 1), na.rm = TRUE),
    total_nonmembers = sum(weight * (membership == 0), na.rm = TRUE),
    .groups = "drop"
  )

# Calculate party proportions among members for each organization type
prop_members <- dat_long %>%
  filter(membership == 1) %>%
  group_by(cntry, party_abbreviation, org_type) %>%
  summarise(
    sum_weight = sum(weight, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  left_join(denom_long, by = c("cntry", "org_type")) %>%
  mutate(prop_members = sum_weight * 100 / total_members) %>%
  select(cntry, party_abbreviation, org_type, prop_members)

# Calculate party proportions among non‐members for each organization type
prop_nonmembers <- dat_long %>%
  filter(membership == 0) %>%
  group_by(cntry, party_abbreviation, org_type) %>%
  summarise(
    sum_weight = sum(weight, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  left_join(denom_long, by = c("cntry", "org_type")) %>%
  mutate(prop_nonmembers = sum_weight * 100 / total_nonmembers) %>%
  select(cntry, party_abbreviation, org_type, prop_nonmembers)

# Merge the two sets of proportions and compute the difference (members - non-members)
dat_table_long <- full_join(prop_members, prop_nonmembers, 
                            by = c("cntry", "party_abbreviation", "org_type")) %>%
  mutate(
    prop_members   = if_else(is.na(prop_members), 0, prop_members),
    prop_nonmembers = if_else(is.na(prop_nonmembers), 0, prop_nonmembers),
    diff_prop      = prop_members - prop_nonmembers
  )

dat_table_long <- dat_table_long %>% 
  ungroup(.) %>% 
  select(cntry, org_type, party_abbreviation, prop_members, prop_nonmembers, diff_prop) %>%
  arrange(cntry, org_type, party_abbreviation) %>% 
  mutate(org_type=case_when(
    org_type=="rel_org" ~ "Religious orgs.", 
    org_type=="arts" ~ "Educ., arts, culture", 
    org_type=="labour" ~ "Labour unions", 
    org_type=="enviro" ~ "Environment, ecology", 
    org_type=="prof" ~ "Professional associat.", 
    org_type=="sports" ~ "Sports or recreation", 
    org_type=="consumer" ~ "Consumer groups", 
    org_type=="other" ~ "Other groups",
    org_type=="humanit" ~  "Humanit. or charity", 
    org_type=="self_help" ~ "Self-help/ mutual aid", 
  )) %>% 
  mutate(org_type = factor(org_type, levels = c(
    "Religious orgs.", 
    "Educ., arts, culture", 
    "Labour unions", 
    "Professional associat.", 
    "Sports or recreation", 
    "Environment, ecology", 
    "Consumer groups", 
    "Humanit. or charity", 
    "Self-help/ mutual aid", 
    "Other groups"
  )))

```

## Appendix B

### Austria

```{r, echo=FALSE, width=6, height=6, warning=FALSE, message=FALSE}

appendix_AU <- dat_table_long %>% 
  filter(cntry=="Austria") %>% 
  select(-cntry) %>% 
  arrange(-prop_nonmembers) %>% 
  mutate(rel_org_value=paste0(round(prop_members, 1), "% (", round(diff_prop, 1), "%)")) %>% 
  select(-prop_nonmembers, -prop_members, -diff_prop) %>% 
  pivot_wider(names_from = party_abbreviation, values_from = rel_org_value) %>% 
  rename("Type of organization" = "org_type") %>% 
  select("Type of organization", "ÖVP", "SPÖ", "FPÖ", "NEOS", "Greens", "PILZ", "Other (AT)", "No party") %>% 
  arrange(`Type of organization`) %>% 
  select(-c("Greens", "PILZ", "Other (AT)", "No party"))

# Define a function that renders a LaTeX table dynamically
render_latex_table <- function(df, caption = "Table", label = NULL) {
  df %>%
    kbl(format = "latex", 
        booktabs = TRUE, 
        linesep = "",
        caption = caption,
        label = label) %>%
    kable_styling(latex_options = c("HOLD_position")) %>%
    row_spec(nrow(df)-1, hline_after = TRUE) %>%
    row_spec(0, bold = TRUE) %>%
    footnote(
      general = "The values represent the share of support for each party among members of the respective organization. In parenthesis it is the difference in percentage point relative to the share among nonmembers of the respective organization.",
      threeparttable = TRUE,
      escape = TRUE
    )
}
 

writeLines(render_latex_table(appendix_AU, 
                   caption = "Share of support for ÖVP, SPÖ, FPÖ and NEOS among members of civil society organizations in Austria", 
                   label = "tab:appendix_AU1"), con = here("appendix_AU1.tex"))

appendix_AU <- dat_table_long %>% 
  filter(cntry=="Austria") %>% 
  select(-cntry) %>% 
  arrange(-prop_nonmembers) %>% 
  mutate(rel_org_value=paste0(round(prop_members, 1), "% (", round(diff_prop, 1), "%)")) %>% 
  select(-prop_nonmembers, -prop_members, -diff_prop) %>% 
  pivot_wider(names_from = party_abbreviation, values_from = rel_org_value) %>% 
  rename("Type of organization" = "org_type") %>% 
  select("Type of organization", "ÖVP", "SPÖ", "FPÖ", "NEOS", "Greens", "PILZ", "Other (AT)", "No party") %>% 
  arrange(`Type of organization`) %>% 
  select(-c("ÖVP", "SPÖ", "FPÖ", "NEOS"))

# Use the function with your object, appendix_AU

writeLines(render_latex_table(appendix_AU, 
                   caption = "Share of support for the Greens, Pilz, other parties and non-voters/ no party identifiers among members of civil society organizations in Austria", 
                   label = "tab:appendix_AU2"), con = here("appendix_AU2.tex"))



```

### France

```{r, echo=FALSE, width=6, height=6, warning=FALSE, message=FALSE}

# Table 1: LREM, FN, LFI, LR
appendix_FR1 <- dat_table_long %>% 
  filter(cntry == "France") %>% 
  select(-cntry) %>% 
  arrange(-prop_nonmembers) %>% 
  mutate(rel_org_value = paste0(round(prop_members, 1), "% (", round(diff_prop, 1), "%)")) %>% 
  select(-prop_nonmembers, -prop_members, -diff_prop) %>% 
  pivot_wider(names_from = party_abbreviation, values_from = rel_org_value) %>% 
  rename("Type of organization" = "org_type") %>% 
  select("Type of organization", "LREM", "FN", "LFI", "LR") %>% 
  arrange(`Type of organization`)

writeLines(render_latex_table(appendix_FR1, 
                   caption = "Share of support for LREM, FN, LFI and LR among members of civil society organizations in France", 
                   label = "tab:appendix_FR1"), 
           con = here("appendix_FR1.tex"))

# Table 2: PS, EELV, MoDem, UDI
appendix_FR2 <- dat_table_long %>% 
  filter(cntry == "France") %>% 
  select(-cntry) %>% 
  arrange(-prop_nonmembers) %>% 
  mutate(rel_org_value = paste0(round(prop_members, 1), "% (", round(diff_prop, 1), "%)")) %>% 
  select(-prop_nonmembers, -prop_members, -diff_prop) %>% 
  pivot_wider(names_from = party_abbreviation, values_from = rel_org_value) %>% 
  rename("Type of organization" = "org_type") %>% 
  select("Type of organization", "PS", "EELV", "MoDem", "UDI") %>% 
  arrange(`Type of organization`)

writeLines(render_latex_table(appendix_FR2, 
                   caption = "Share of support for PS, EELV, MoDem and UDI among members of civil society organizations in France", 
                   label = "tab:appendix_FR2"), 
           con = here("appendix_FR2.tex"))


# Table 3: PCF, DLF, Other (FR), No party
appendix_FR3 <- dat_table_long %>% 
  filter(cntry == "France") %>% 
  select(-cntry) %>% 
  arrange(-prop_nonmembers) %>% 
  mutate(rel_org_value = paste0(round(prop_members, 1), "% (", round(diff_prop, 1), "%)")) %>% 
  select(-prop_nonmembers, -prop_members, -diff_prop) %>% 
  pivot_wider(names_from = party_abbreviation, values_from = rel_org_value) %>% 
  rename("Type of organization" = "org_type") %>% 
  select("Type of organization", "PCF", "DLF", "Other (FR)", "No party") %>% 
  arrange(`Type of organization`)

writeLines(render_latex_table(appendix_FR3, 
                   caption = "Share of support for PCF, DLF, Other (FR) and No party among members of civil society organizations in France", 
                   label = "tab:appendix_FR3"), 
           con = here("appendix_FR3.tex"))

```

### Germany

```{r, echo=FALSE, width=6, height=6, warning=FALSE, message=FALSE}

# Table 1: CDU/CSU, SPD, Die Grünen, FDP
appendix_DE1 <- dat_table_long %>% 
  filter(cntry == "Germany") %>% 
  select(-cntry) %>% 
  arrange(-prop_nonmembers) %>% 
  mutate(rel_org_value = paste0(round(prop_members, 1), "% (", round(diff_prop, 1), "%)")) %>% 
  select(-prop_nonmembers, -prop_members, -diff_prop) %>% 
  pivot_wider(names_from = party_abbreviation, values_from = rel_org_value) %>% 
  rename("Type of organization" = "org_type") %>% 
  select("Type of organization", "CDU/CSU", "SPD", "Die Grünen", "FDP (DE)") %>% 
  arrange(`Type of organization`)

writeLines(render_latex_table(appendix_DE1, 
                   caption = "Share of support for CDU/CSU, SPD, Die Grünen and FDP among members of civil society organizations in Germany", 
                   label = "tab:appendix_DE1"), 
           con = here("appendix_DE1.tex"))


# Table 2: AfD, LINKE, Other (DE), No party
appendix_DE2 <- dat_table_long %>% 
  filter(cntry == "Germany") %>% 
  select(-cntry) %>% 
  arrange(-prop_nonmembers) %>% 
  mutate(rel_org_value = paste0(round(prop_members, 1), "% (", round(diff_prop, 1), "%)")) %>% 
  select(-prop_nonmembers, -prop_members, -diff_prop) %>% 
  pivot_wider(names_from = party_abbreviation, values_from = rel_org_value) %>% 
  rename("Type of organization" = "org_type") %>% 
  select("Type of organization", "AfD", "LINKE", "Other (DE)", "No party") %>% 
  arrange(`Type of organization`)

writeLines(render_latex_table(appendix_DE2, 
                   caption = "Share of support for AfD, LINKE, Other (DE) and No party among members of civil society organizations in Germany", 
                   label = "tab:appendix_DE2"), 
           con = here("appendix_DE2.tex"))


```

### The Netherlands

```{r, echo=FALSE, width=6, height=6, warning=FALSE, message=FALSE}

# Table 1: VVD, D66, CDA, PVV
appendix_NL1 <- dat_table_long %>% 
  filter(cntry == "Netherlands") %>% 
  select(-cntry) %>% 
  arrange(-prop_nonmembers) %>% 
  mutate(rel_org_value = paste0(round(prop_members, 1), "% (", round(diff_prop, 1), "%)")) %>% 
  select(-prop_nonmembers, -prop_members, -diff_prop) %>% 
  pivot_wider(names_from = party_abbreviation, values_from = rel_org_value) %>% 
  rename("Type of organization" = "org_type") %>% 
  select("Type of organization", "VVD", "D66", "CDA", "PVV") %>% 
  arrange(`Type of organization`)

writeLines(render_latex_table(appendix_NL1, 
                   caption = "Share of support for VVD, D66, CDA and PVV among members of civil society organizations in the Netherlands", 
                   label = "tab:appendix_NL1"), 
           con = here("appendix_NL1.tex"))

# Table 2: SP (NL), GL, FvD, JA21
appendix_NL2 <- dat_table_long %>% 
  filter(cntry == "Netherlands") %>% 
  select(-cntry) %>% 
  arrange(-prop_nonmembers) %>% 
  mutate(rel_org_value = paste0(round(prop_members, 1), "% (", round(diff_prop, 1), "%)")) %>% 
  select(-prop_nonmembers, -prop_members, -diff_prop) %>% 
  pivot_wider(names_from = party_abbreviation, values_from = rel_org_value) %>% 
  rename("Type of organization" = "org_type") %>% 
  select("Type of organization", "SP (NL)", "GL", "FvD", "JA21") %>% 
  arrange(`Type of organization`)

writeLines(render_latex_table(appendix_NL2, 
                   caption = "Share of support for SP (NL), GL, FvD and JA21 among members of civil society organizations in the Netherlands", 
                   label = "tab:appendix_NL2"), 
           con = here("appendix_NL2.tex"))

# Table 3: CU, BBB, PvdA, PvdD
appendix_NL3 <- dat_table_long %>% 
  filter(cntry == "Netherlands") %>% 
  select(-cntry) %>% 
  arrange(-prop_nonmembers) %>% 
  mutate(rel_org_value = paste0(round(prop_members, 1), "% (", round(diff_prop, 1), "%)")) %>% 
  select(-prop_nonmembers, -prop_members, -diff_prop) %>% 
  pivot_wider(names_from = party_abbreviation, values_from = rel_org_value) %>% 
  rename("Type of organization" = "org_type") %>% 
  select("Type of organization", "CU", "BBB", "PvdA", "PvdD") %>% 
  arrange(`Type of organization`)

writeLines(render_latex_table(appendix_NL3, 
                   caption = "Share of support for CU, BBB, PvdA and PvdD among members of civil society organizations in the Netherlands", 
                   label = "tab:appendix_NL3"), 
           con = here("appendix_NL3.tex"))



# Table 4: SGP, 50Plus, Volt
appendix_NL4 <- dat_table_long %>% 
  filter(cntry == "Netherlands") %>% 
  select(-cntry) %>% 
  arrange(-prop_nonmembers) %>% 
  mutate(rel_org_value = paste0(round(prop_members, 1), "% (", round(diff_prop, 1), "%)")) %>% 
  select(-prop_nonmembers, -prop_members, -diff_prop) %>% 
  pivot_wider(names_from = party_abbreviation, values_from = rel_org_value) %>% 
  rename("Type of organization" = "org_type") %>% 
  select("Type of organization", "SGP", "50Plus", "Volt") %>% 
  arrange(`Type of organization`)

writeLines(render_latex_table(appendix_NL4, 
                   caption = "Share of support for SGP, 50Plus and Volt among members of civil society organizations in the Netherlands", 
                   label = "tab:appendix_NL4"), 
           con = here("appendix_NL4.tex"))

# Table 5: Other (NL), No party
appendix_NL5 <- dat_table_long %>% 
  filter(cntry == "Netherlands") %>% 
  select(-cntry) %>% 
  arrange(-prop_nonmembers) %>% 
  mutate(rel_org_value = paste0(round(prop_members, 1), "% (", round(diff_prop, 1), "%)")) %>% 
  select(-prop_nonmembers, -prop_members, -diff_prop) %>% 
  pivot_wider(names_from = party_abbreviation, values_from = rel_org_value) %>% 
  rename("Type of organization" = "org_type") %>% 
  select("Type of organization", "Other (NL)", "No party") %>% 
  arrange(`Type of organization`)

writeLines(render_latex_table(appendix_NL5, 
                   caption = "Share of support for Other (NL) and No party among members of civil society organizations in the Netherlands", 
                   label = "tab:appendix_NL5"), 
           con = here("appendix_NL5.tex"))


```

### Switzerland

```{r, echo=FALSE, width=6, height=6, warning=FALSE, message=FALSE}

# Table 1: SVP, SP (CH), FDP (CH), CVP
appendix_CH1 <- dat_table_long %>% 
  filter(cntry == "Switzerland") %>% 
  select(-cntry) %>% 
  arrange(-prop_nonmembers) %>% 
  mutate(rel_org_value = paste0(round(prop_members, 1), "% (", round(diff_prop, 1), "%)")) %>% 
  select(-prop_nonmembers, -prop_members, -diff_prop) %>% 
  pivot_wider(names_from = party_abbreviation, values_from = rel_org_value) %>% 
  rename("Type of organization" = "org_type") %>% 
  select("Type of organization", "SVP", "SP (CH)", "FDP (CH)", "CVP") %>% 
  arrange(`Type of organization`)

writeLines(render_latex_table(appendix_CH1, 
                   caption = "Share of support for SVP, SP (CH), FDP (CH) and CVP among members of civil society organizations in Switzerland", 
                   label = "tab:appendix_CH1"), 
           con = here("appendix_CH1.tex"))

# Table 2: GPS, GLP, EVP, BDP
appendix_CH2 <- dat_table_long %>% 
  filter(cntry == "Switzerland") %>% 
  select(-cntry) %>% 
  arrange(-prop_nonmembers) %>% 
  mutate(rel_org_value = paste0(round(prop_members, 1), "% (", round(diff_prop, 1), "%)")) %>% 
  select(-prop_nonmembers, -prop_members, -diff_prop) %>% 
  pivot_wider(names_from = party_abbreviation, values_from = rel_org_value) %>% 
  rename("Type of organization" = "org_type") %>% 
  select("Type of organization", "GPS", "GLP", "EVP", "BDP") %>% 
  arrange(`Type of organization`)

writeLines(render_latex_table(appendix_CH2, 
                   caption = "Share of support for GPS, GLP, EVP and BDP among members of civil society organizations in Switzerland", 
                   label = "tab:appendix_CH2"), 
           con = here("appendix_CH2.tex"))

# Table 3: PST, EDU, AL
appendix_CH3 <- dat_table_long %>% 
  filter(cntry == "Switzerland") %>% 
  select(-cntry) %>% 
  arrange(-prop_nonmembers) %>% 
  mutate(rel_org_value = paste0(round(prop_members, 1), "% (", round(diff_prop, 1), "%)")) %>% 
  select(-prop_nonmembers, -prop_members, -diff_prop) %>% 
  pivot_wider(names_from = party_abbreviation, values_from = rel_org_value) %>% 
  rename("Type of organization" = "org_type") %>% 
  select("Type of organization", "PST", "EDU", "AL") %>% 
  arrange(`Type of organization`)

writeLines(render_latex_table(appendix_CH3, 
                   caption = "Share of support for PST, EDU and AL among members of civil society organizations in Switzerland", 
                   label = "tab:appendix_CH3"), 
           con = here("appendix_CH3.tex"))

# Table 4: Other (CH), No party
appendix_CH4 <- dat_table_long %>% 
  filter(cntry == "Switzerland") %>% 
  select(-cntry) %>% 
  arrange(-prop_nonmembers) %>% 
  mutate(rel_org_value = paste0(round(prop_members, 1), "% (", round(diff_prop, 1), "%)")) %>% 
  select(-prop_nonmembers, -prop_members, -diff_prop) %>% 
  pivot_wider(names_from = party_abbreviation, values_from = rel_org_value) %>% 
  rename("Type of organization" = "org_type") %>% 
  select("Type of organization", "Other (CH)", "No party") %>% 
  arrange(`Type of organization`)

writeLines(render_latex_table(appendix_CH4, 
                   caption = "Share of support for Other (CH) and No party among members of civil society organizations in Switzerland", 
                   label = "tab:appendix_CH4"), 
           con = here("appendix_CH4.tex"))

rm(list = ls(pattern = "^appendix_"))

```

## Appendix B, classification table

```{r, echo=FALSE, width=6, height=6, warning=FALSE, message=FALSE}

families <- dat_table_long %>% 
  select(cntry, party_abbreviation) %>%
  unique() %>% 
  filter(!grepl("No party", party_abbreviation)) %>%
  filter(!grepl("Other", party_abbreviation)) %>% 
  mutate(party_abbreviation=stringi::stri_trans_general(party_abbreviation, 'latin-ascii')) %>% 
  mutate(party_abbreviation=gsub("\\s*\\([^\\)]+\\)", "", party_abbreviation))
  # write.csv("families.csv")

ches_families <- read_dta(here("CHES dataset means v3.dta")) %>%
  select(country, party, family) %>%
  distinct() %>%
  mutate(country=as_factor(country)) %>%
  filter(country %in% c("aus", "fr", "ge", "nl", "swi")) %>% 
  mutate(cntry=case_when(
    country=="aus" ~ "Austria",
    country=="fr" ~ "France",
    country=="ge" ~ "Germany",
    country=="nl" ~ "Netherlands",
    country=="swi" ~ "Switzerland"
  )) %>%
  mutate(family=as_factor(family)) %>%
  select(-country) %>% 
  rename(party_abbreviation=party) %>% 
  mutate(party_abbreviation=stringi::stri_trans_general(party_abbreviation, 'latin-ascii')) %>% 
  mutate(party_abbreviation=case_when(cntry=="Austria" & party_abbreviation== "Grune" ~ "Greens",
                                      cntry=="Germany" & party_abbreviation== "CDU" ~ "CDU/CSU",
                                      cntry=="Germany" & party_abbreviation== "Grunen" ~ "Die Grunen",
                                      cntry=="Netherlands" & party_abbreviation== "50PLUS" ~ "50Plus",
                                      TRUE ~ party_abbreviation))

families_merged <- left_join(families, ches_families, by = c("cntry", "party_abbreviation")) %>% 
  mutate(family = case_when(
  cntry=="Austria" & party_abbreviation == "PILZ" ~ "rad left",
  cntry=="France" & party_abbreviation == "LFI" ~ "rad left",
  cntry=="France" & party_abbreviation == "UDI" ~ "liberal",
  cntry=="Netherlands" & party_abbreviation == "BBB" ~ "rad right",
  cntry=="Netherlands" & party_abbreviation == "JA21" ~ "rad right",
  cntry=="Netherlands" & party_abbreviation == "Volt" ~ "rad left",
  cntry=="Switzerland" & party_abbreviation == "SVP" ~ "rad right",
  cntry=="Switzerland" & party_abbreviation == "SP" ~ "socialist",
  cntry=="Switzerland" & party_abbreviation == "FDP" ~ "liberal",
  cntry=="Switzerland" & party_abbreviation == "CVP" ~ "christdem",
  cntry=="Switzerland" & party_abbreviation == "GLP" ~ "green",
  cntry=="Switzerland" & party_abbreviation == "GPS" ~ "green",
  cntry=="Switzerland" & party_abbreviation == "BDP" ~ "cons",
  cntry=="Switzerland" & party_abbreviation == "EDU" ~ "confessional",
  cntry=="Switzerland" & party_abbreviation == "EVP" ~ "confessional",
  cntry=="Switzerland" & party_abbreviation == "AL" ~ "rad left",
  cntry=="Switzerland" & party_abbreviation == "PST" ~ "rad left",
  cntry=="Germany" & party_abbreviation == "AfD" ~ "rad right",
  cntry=="Netherlands" & party_abbreviation == "50Plus" ~ "cons",
  TRUE ~ family)) 

```

```{r, echo=FALSE, width=6, height=6, warning=FALSE, message=FALSE}

dat_plot <- dat_table_long %>% 
  # filter(!grepl("Other", party_abbreviation)) %>% 
  mutate(party_abbreviation=stringi::stri_trans_general(party_abbreviation, 'latin-ascii')) %>% 
  mutate(party_abbreviation=gsub("\\s*\\([^\\)]+\\)", "", party_abbreviation)) %>% 
  left_join(families_merged, by = c("cntry", "party_abbreviation")) %>% 
  mutate(orientation=case_when(
    party_abbreviation=="Other" ~ "Other",
    party_abbreviation=="No party" ~ "None",
    family %in% c("christdem", "cons") ~ "Right-wing",
    family %in% c("socialist") ~ "Left-wing",
    family %in% c("confessional", "liberal") ~ "Other",
    family %in% c("green") ~ "Green",
    family %in% c("rad left") ~ "Radical-left",
    family %in% c("rad right") ~ "Radical-right")) 

class_table <- dat_plot %>% 
  filter(!(cntry %in% c("Netherlands", "Switzerland"))) %>% 
  select(cntry, party_abbreviation, family, orientation) %>%
  distinct() %>% 
  arrange(cntry, party_abbreviation, family) %>% 
  kbl(format = "latex", 
        booktabs = TRUE, 
        linesep = "",
        caption = "Classifying parties into families and ideological orientations in Austria, Germany and France",
        label = "tab:class_table",
      threeparttable=TRUE) %>%
    kable_styling(latex_options = c("HOLD_position")) %>%
    row_spec(nrow(df)-1, hline_after = TRUE) %>%
    row_spec(0, bold = TRUE) %>% 
  footnote(general = "The family classification is mostly based on the Chapel Hill Expert Survey (CHES).",
           escape=TRUE,
           threeparttable = TRUE
    )

writeLines(class_table, con = here("party_class_table1.tex"))

class_table <- dat_plot %>% 
  filter(cntry %in% c("Netherlands", "Switzerland")) %>% 
  select(cntry, party_abbreviation, family, orientation) %>%
  distinct() %>% 
  arrange(cntry, party_abbreviation, family) %>% 
  kbl(format = "latex", 
        booktabs = TRUE, 
        linesep = "",
        caption = "Classifying parties into families and ideological orientations in the Netherlands and Switzerland",
        label = "tab:class_table",
      threeparttable=TRUE) %>%
    kable_styling(latex_options = c("HOLD_position")) %>%
    row_spec(nrow(df)-1, hline_after = TRUE) %>%
    row_spec(0, bold = TRUE) %>% 
  footnote(general = "The family classification is mostly based on the Chapel Hill Expert Survey (CHES). Parties in Switzerland are not covered by CHES, these were classified by the authors.",
           escape=TRUE,
           threeparttable = TRUE
    )

writeLines(class_table, con = here("party_class_table2.tex"))

dat_plot <- dat_plot %>%
  select(cntry, org_type, prop_members, prop_nonmembers, orientation) %>% 
  group_by(cntry, org_type, orientation) %>% 
  mutate_at(vars(prop_members, prop_nonmembers), ~sum(., na.rm = TRUE)) %>% 
  ungroup() %>%
  distinct() %>% 
  mutate(orientation=factor(orientation, levels=c("Radical-right", "Right-wing", "Left-wing", "Radical-left",  "Green", "Other", "None"))) %>% 
  mutate(diff_prop=prop_members-prop_nonmembers) 

```

## Figure 3, main text

```{r, echo=FALSE, width=6, height=6, warning=FALSE, message=FALSE}

library(dplyr)
library(scales)
library(ggplot2)
library(ggtext)  # for geom_richtext

# Assign quadrants.
dat_plot2 <- subset(dat_plot, orientation %in% c("Radical-right", "Green")) %>% 
  select(-c(prop_members, prop_nonmembers)) %>% 
  mutate(orientation=ifelse(orientation=="Radical-right", "RadicalRight", "Green")) %>%
  pivot_wider(names_from = orientation, values_from = diff_prop) %>%
  mutate(quadrant = case_when(
    RadicalRight < 0 & Green > 0  ~ "I.",
    RadicalRight >= 0 & Green > 0 ~ "II.",
    RadicalRight >= 0 & Green <= 0 ~ "III.",
    RadicalRight < 0 & Green <= 0 ~ "IV."
  ))

# Manually assign fill colors to each org_type.
org_type_colors <- c(
  "Religious orgs."        = "#CC79A7",
  "Educ., arts, culture"   = "#0072B2",
  "Labour unions"          = "#D55E00",
  "Professional associat." = "#F0E442",
  "Sports or recreation"   = "#E69F00",
  "Environment, ecology"   = "#009E73",
  "Consumer groups"        = "#56B4E9",
  "Humanit. or charity"    = "#A65628",
  "Self-help/ mutual aid"  = "#F781BF",
  "Other groups"           = "#999999"
)

# Calculate symmetric axis limits.
max_lim <- max(abs(dat_plot2$RadicalRight), abs(dat_plot2$Green), na.rm = TRUE)

# Calculate counts, shares, and build the rich text label.
quad_data <- dat_plot2 %>%
  count(quadrant) %>%
  mutate(share = n / sum(n),
         roman = quadrant,
         percentage = paste0("(", percent(share, accuracy = 1), ")"),
         # Use an absolute font size for the percentage (4pt) and leave the roman numeral at the default size.
         rich_label = paste0("<span style='font-weight:bold;'>", roman,
                             "</span><br/><span style='font-style:italic; font-size:11pt;'>", 
                             percentage, "</span>")
  )

# Define fixed positions for quadrant labels.
quad_positions <- data.frame(
  quadrant = c("I.", "II.", "III.", "IV."),
  x = c(-max_lim, max_lim, max_lim, -max_lim),
  y = c(max_lim, max_lim, -8, -8),
  hjust = c(0, 1, 1, 0),
  vjust = c(1, 1, 0, 0)
)

# Merge positions with label information.
quad_labels <- merge(quad_positions, quad_data, by = "quadrant")

# Create the plot.
ggplot(dat_plot2, aes(x = RadicalRight, y = Green, shape = cntry, fill = org_type)) +
  geom_point(size = 3, stroke = 1, color = "black") +
  geom_vline(xintercept = 0, linetype = "dashed", color = "grey") +
  geom_hline(yintercept = 0, linetype = "dashed", color = "grey") +
  ggtext::geom_richtext(data = quad_labels,
                        mapping = aes(x = x, y = y, label = rich_label,
                                      hjust = hjust, vjust = vjust),
                        inherit.aes = FALSE,
                        size = 5,      # overall base size
                        fill = NA,     # no background
                        label.color = NA) +
  coord_fixed(xlim = c(-max_lim, max_lim), ylim = c(-8, max_lim)) +
  labs(
    x = "Difference in far right parties' popularity\n among members minus among nonmembers",
    y = "Difference in green parties' popularity\n among members minus among nonmembers",
    shape = "Country:",
    fill = "Type of organization:"
  ) +
  scale_fill_manual(values = org_type_colors) +
  scale_shape_manual(values = c(21, 22, 23, 24, 25)) +
  theme_bw() +
  theme(
    legend.position = "bottom",
    legend.box = "vertical"
  ) +
  guides(
    shape = guide_legend(order = 1, ncol = 2),
    fill  = guide_legend(order = 2, ncol = 2,
                         override.aes = list(shape = 21, color = "black"))
  )

# ggsave(
#   filename = "civsoc_diff_scatter_plot.png",
#   dpi = 600,
#   scale = 1.2,
#   width = 5, height = 7,
#   units = "in"
# )

```


## Figure 2, main text

- this takes the party electorate as 100 percent, so it's not making a difference between small and large parties.

```{r, echo=FALSE, width=6, height=6, warning=FALSE, message=FALSE}

dat_plot <- dat %>% 
  group_by(cntry) %>% 
  mutate(total=sum(weight)) %>% 
  group_by(cntry, party_abbreviation) %>%
  mutate(total_party=sum(weight)) %>% 
  group_by(cntry, party_abbreviation, involvement_2) %>%
  mutate(active_electorate=sum(weight)) %>%
  ungroup() %>%
  select(cntry, party_abbreviation, total, total_party, 
         active_electorate, involvement_2) %>%
  distinct() %>% 
  filter(!is.na(party_abbreviation)) %>%
  filter(involvement_2==1) %>% 
  mutate(party_perc=total_party/total*100,
         active_electorate_perc=active_electorate/total_party*100) %>% 
  filter(!grepl("Other", party_abbreviation)) %>% 
  filter(!grepl("No party", party_abbreviation)) %>% 
   mutate(party_abbreviation=stringi::stri_trans_general(party_abbreviation, 'latin-ascii')) %>% 
  mutate(party_abbreviation=gsub("\\s*\\([^\\)]+\\)", "", party_abbreviation)) %>% 
  left_join(families_merged, by = c("cntry", "party_abbreviation")) %>% 
  mutate(orientation=case_when(
    party_abbreviation=="Other" ~ "Other",
    party_abbreviation=="No party" ~ "None",
    family %in% c("christdem", "cons") ~ "Right-wing",
    family %in% c("socialist") ~ "Left-wing",
    family %in% c("confessional", "liberal") ~ "Other",
    family %in% c("green") ~ "Green",
    family %in% c("rad left") ~ "Radical-left",
    family %in% c("rad right") ~ "Radical-right"))  %>% 
  group_by(cntry) %>% 
  mutate(active_electorate_perc=active_electorate_perc-mean(active_electorate_perc, na.rm = TRUE)) %>%
  ungroup() %>% 
  mutate(party_abbreviation=case_when(cntry=="Germany" ~ paste0(party_abbreviation, " (DE)"),
                                      cntry=="Switzerland" ~ paste0(party_abbreviation, " (CH)"),
                                      cntry=="Netherlands" ~ paste0(party_abbreviation, " (NL)"),
                                      cntry=="Austria" ~ paste0(party_abbreviation, " (AU)"),
                                      cntry=="France" ~ paste0(party_abbreviation, " (FR)"),
                                      TRUE ~ party_abbreviation)) %>% 
  unique() %>% 
  mutate(family=case_when(
    family %in% c("christdem", "socialist", "liberal", "rad left", "cons", "confessional") ~ "other",
    TRUE ~ family))

party_colors <- c(
  # christdem    = "orange",
  # socialist    = "red",
  `rad right`  = "darkblue",
  green        = "green",
  other = "gray60"
  # liberal      = "yellow",
  # `rad left`   = "purple",
  # cons         = "black",
  # confessional = "brown"
)

ggplot(dat_plot, aes(x = reorder(party_abbreviation, active_electorate_perc), 
                     y = active_electorate_perc, fill = family)) +
  geom_bar(stat = "identity", color = "black", linewidth=0.3) +
  theme_bw() +
  labs(x = "", y = "Percentage of voters active in at least one \n organization relative to the country-mean") +
  scale_fill_manual(
    values = party_colors,
    # Set the order explicitly:
    breaks = c(
      # "rad left", "socialist", "green", "liberal", 
               # "christdem", "confessional", "cons", "rad right"
                "green", "rad right", "other"),
    labels = c(
      # "rad left"     = "Radical Left",
      # "socialist"    = "Socialist",
      "green"        = "Green",
      # "liberal"      = "Liberal",
      # "christdem"    = "Christian Democracy",
      # "confessional" = "Confessional",
      # "cons"         = "Conservative",
      "rad right"    = "Far right",
      "other"        = "Other"
    )
  ) +
  theme(
    axis.title.x = element_blank(),
    axis.text.x  = element_text(angle = 90, vjust = 0.5, hjust = 1),
    legend.position = "bottom",
    legend.title = element_blank()
  ) +
  guides(fill = guide_legend(ncol = 3, byrow=TRUE))

# ggsave(
#     filename = "party_bar_plot.png",
#     dpi=600,
#     width = 7, height = 5,
#     units = "in"
# )


```



```{r, echo=FALSE, width=6, height=6, warning=FALSE, message=FALSE}

```